PHP me MYSQL
Ne seksionet e meparshme shpjeguam se cfare jane databazat relacionale, trajtuam menyren e ndertimit te nje databaze, shpjeguam bazat e SQL-se te nevojshme per vazhdimin e shpjegimit te PHP-se ne bashkeveprim me MySQL. Ne kete seksion do te perpiqemi te ndertojme sa me shume shembuj qe te tregojme menyren sesi bashkevepron PHP-ja me MySQL per te bere nje faqe dinamike dhe funksionale. Dukeqenese kemi njohuri edhe nga PHP e orientuar nga objekti, do te perdorim disa klasa te gatshme ne PHP te cilat na ndihmojne per t'u lidhur me sistemet e menaxhimit te bazes se te dhenave, ne kete rast me MySQL.
PDO
PDO-ja e cila vjen nga fjala PHP Data Objects, percakton nje nderfaqe konsistente per te aksesuar bazat e te dhenave ne PHP. PDO-ja na ofron nje shtrese abstrakte per aksesimin e te dhenave, qe do te thote se pavaresisht se cfare sistemi databaze po perdorim, ofron te njejtat funksionalitete per te derguar deklarata SQL drejt databazes, per te shtuar, modifikuar, fshire ose per te marre te dhena.
Ne te vertete PDO-ja eshte thjeshte nje klase qe vjen bashke me PHP-ne. Nuk kemi nevoje per importime te jashtme. Mjafton te ndertojme nje objekt te kesaj klase dhe na jepet mundesia qe te perdorim funksionalitetet e saj, duke therritur metoda te ndryshme. Keto metoda sherbejne per te derguar deklarata SQL drejt databazes ne menyre qe te kryejme veprime te ndryshme si shtime, modifikime, fshirje ose marrje rekordesh.
Nje objekt i klases PDO
eshte thjeshte nje lidhje qe krijohet me bazen e te dhenave, e specifikuar sipas parametrave qe kalojme kur ndertojme objektin:
<?php
$host = "127.0.0.1"; //ose thjesht: localhost
$user = "root";
$password = ""; //Supozojme qe nuk kemi password per userin root
$db_name = "fakulteti";
$connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
PDO-ja kerkon 3 parametra ne konstruktor:
- Hosti dhe emri i databazes - Stringe ne formatin:
mysql:host=______;dbname=_____
- User - Username per t'u loguar ne MySQL
- Password - Fjalekalimi per userin ne fjale
Gjate lidhjes me bazen e te dhenave mund te shkaktohen probleme te ndryshme. Per te trajtuar keto probleme ne menyren e duhur duhet te perdorim blloqet try-catch
.
<?php
try {
$connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Lidhja u krye me sukses.";
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
}
Ne rastin e mesiperm, nese lidhja kryhet me sukses dhe nuk gjenerohet ndonje gabim nga PDO-ja do te printohet mesazhi: Lidhja u krye me sukses.
Perndryshe, nese lidhja deshton ne momentin kur krijojme objektin, atehere ekzekutimi i kodit kalon ne bllokun catch(PDOException $ex)
i cili do te printoje tekstin Lidhja Deshtoi:
te shoqeruar me mesazhin qe vjen nga objekti i klases PDOException
.
Klasa PDOException
eshte nje avantazh i madh i PDO-se, pasi me ane te saj mund te trajtojme te gjitha llojet e problemeve te cilat mund te ndodhin gjate lidhjes me databazen gjate ekzekutimit te SQL-se etj.
Pasi te kemi perfunduar veprimet me bazen e te dhenave, gjithmone duhet te mbyllim lidhjen me te. Mjafton t'i japim vleren NULL
references qe mban lidhjen me databazen.
<?php
//Mbyllja e lidhjes me bazen e te dhenave:
$connection = NULL;
Ne momentin qe hapim nje lidhje me bazen e te dhenave jemi te lire te dergojme drejt saj deklarata SQL.
Ajo cfare do te bejme, eshte ndertimi i nje klase te personalizuar nga ne per te kryer veprime me bazen e te dhenave. Le te krijojme nje klase me emrin Database
:
<?php
class Database {
private $connection;
function __construct() {
try {
$this->connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
exit;
}
}
} // Fundi i klases Database
Ne konstruktorin e saj do te permbaje kodin per lidhjen me bazen e te dhenave, ne menyre qe sa here qe krijojme nje objekt te kesaj klase, te lidhemi me bazen e te dhenave:
<?php
$db = new Database();
Me krijimin e objektit $db
ekzekutohet konstruktori i klases Database
, ndaj krijohet edhe lidhja me bazen e te dhenave. Ne rast se lidhja eshte e suksesshme variabli anetar $connection
do te mbaje nje objekt te ksaj lidhjeje. Do te shohim me poshte qe kete objekt do ta shfrytezojme per te derguar deklarata SQL ne databaze, dhe per ti ekzekutuar ato.
Qellimi i krijimit te klases Database
eshte qe te krijojme disa metoda te ndryshme te saj per te kryer veprime te ndryshme si shtim te nje rekordi ne nje tabele, modifikim apo fshirje etj. Ne vijim, gjate shpjegimit sesi realizohen keto veprime duke shfrytezuar klasen PDO
, do te implementojme edhe metoda te klases Database
si p.sh. select(...)
, insert(...)
, update(...)
dhe delete(...)
.
Shtimi i nje rekordi ne nje tabele
Per te shtuar rekorde ne nje tabele do te perdorim deklaratat e pergatitura (ang. prepared statements). Ekzekutimi i nje deklarate te pergatitur kalon ne dy faza:
- Ne fazen e pergatitjes dergohet ne server nje deklarate ne forme shablloni qe permban disa parametra te formes
:emri_parametrit
ne vend te vlerave reale te fushave. - Ne fazen e dyte dergohen ne server vetem vlerat te lidhura me parametrat specifik.
Arsyeja pse ndiqen keto dy faza eshte eficenca e larte dhe shpejtesia e ekzekutimit.
Ne kete rast, deklarata SQL qe nisim ka formen e meposhtme:
INSERT INTO departamentet (emri, pershkrimi) VALUES (:emri, :pershkrimi);
Nese deshirojme te shtojme nje departament ne tabelen departamentet
, ndjekim rrjedhen e meposhtme:
<?php
// Supozojme qe lidhja $connection ishte e suksesshme
$stmt = $connection->prepare("INSERT INTO departamentet (emri, pershkrimi) VALUES (:emri, :pershkrimi);");
// Vlerat e rekordit qe duam te shtojme ne tabele:
$emri = "Departamenti i Inxhinierise Informatike";
$pershkrimi = "Pershkrimi per departamentin e inxhinierise informatike.";
//Behet lidhja e parametrave me vlerat reale:
$stmt->bindValue(':emri', $emri);
$stmt->bindValue(':pershkrimi', $pershkrimi);
// Faza e ekzekutimit:
$rezultati = $stmt->execute();
Fillimisht pergatitet deklarata me metoden $connection->prepare(...)
. Ne vend te vlerave reale te fushave vendosim disa parametra ne formen :emri_parametrit
. Kur therrasim metoden prepare(...)
, ajo do te na ktheje nje objekt te cilin ne e kemi quajtur $stmt
. Me ane te ketij objekti percaktojme vlerat e parametrave duke perdorur metoden bindValue(...)
i cili pranon dy argumente, i pari merr ne forme stringe emrin e parametrit te kaluar ne deklaraten SQL p.sh. :emri
, ndersa argumenti i dyte merr vleren qe do te vendoset ne korrespondence me kete parameter. Ne fund bejme ekzekutimin final duke therritur metoden $stmt->execute();
. Kjo metode do te na ktheje TRUE
nese shtimi i rekordit ishte i suksesshem , ose FALSE
nese deshtoi.
Rezultatin qe kthen metoda execute(...)
e kemi ruajtur ne variablin $rezultati
. Me poshte tregohet nje shembull sesi mund te merret id-ja e rekordit te sapo shtuar ne databaze. Ne rast se shtimi i rekordit ishte i sakte kemi, ruajme id-ne e rekordit te shtuar ne variablin $id
:
<?php
if ($rezultati) {
$id = $connection->lastInsertId(); // 1
}
Pas ekzekutimit te kodit te mesiperm, nese bejme nje SELECT
ne databaze do te shohim qe rekordi i ri gjendet ne tabele:
Komanda:
SELECT * FROM departamentet;
id | emri | pershkrimi |
---|---|---|
1 | Departamenti i Inxhinierise Informatike | Pershkrimi per departamentin e inxhinierise informatike. |
Pasi trajtuam menyren sesi shtohet nje rekord duke shfrytezuar klasen PDO
, le te ndertojme nje metode te klases Database
te quajtur insert(...)
e cila do te jete dinamike, ne menyre te tille qe te funksionoje per cdo lloj tabele, dhe te mund te shtoje rekorde me vlera te ndryshme.
<?php
function insert(string $table, array $field_values) {
}
Funksioni insert(...)
do te pranoje dy argumente:
- Argumenti i pare do te jete nje string qe mban emrin e tabeles ne te cilen do te bejme shtimin e rekordit
- Argumenti i dyte do te jete nje array associative
key => value
i cili do te mbaje sikeys
emrat e fushave te tabeles, dhe sivalues
do te mbaje vlerat perkatese qe do te kene keto fusha ne rekordin e ri.
P.sh. ne rast se duam te shtojme nje rekord ne tabelen departamentet
, parametrat qe do te kalohen do te kene vlerat e meposhtme:
<?php
$table = "departamentet";
$field_values = [
"emri" => "Departamenti i Elektronikes dhe Telekomunikacionit",
"pershkrimi" => "Pershkrimi i departamentit te elektronikes dhe telekomunikacionit."
];
Para se te implementojme metoden insert(...)
, duhet te kemi parasysh qe deklarata SQL e cila do te dergohet duhet te jete dinamike p.sh. ne rast se po shtohet rekordi i meposhtem:
<?php
$table = "tabela_1";
$field_values = [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
"fusha_3" => "vlera_3"
];
Deklarata SQL e parametrizuar duhet te jete si me poshte:
INSERT INTO tabela_1 (fusha_1, fusha_2, fusha_3) VALUES (:fusha_1, :fusha_2, :fusha_3);
Per arsye siguri, emrin e tabeles dhe te fushave duhet ta vendosim ndermjet shenjave ` (backquote), qe te mos kene perplasje me fjalet kyce (sintaksa) te SQL-se. Ne kete rast, per lehtesi shpjegimi le ti leme pa to.
Per te ndertuar nje SQL-ne e mesiperme ne menyre dinamike, duhet te perdorim PHP-ne pasi asnjehere nuk dihet sesa do te jete numri i fushave.
Ndertojme ne menyre dinamike emrat e fushave te ndare me presje:
<?php
// P.sh. kemi fushat e meposhtme:
$field_values = [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
"fusha_3" => "vlera_3"
];
$fushat = implode(',', array_keys($field_values));
echo $fushat; // Rezultati: fusha_1, fusha_2, fusha_3
Funksioni array_keys(...)
merr si argument nje array dhe kthen si output nje array tjeter i cili permban listen me celesa. Ne kete rast p.sh. array_keys($field_values)
kthen nje array me permbajtjen e meposhtme:
Array (
[0] => fusha_1,
[1] => fusha_2,
[2] => fusha_3
)
Me pas, funksioni implode(...)
merr te gjitha elementet e ketij array dhe i bashkon me shenjen presje (,
), si output na jep nje stringe me elementet e bashkuar: fusha_1, fusha_2, fusha_3
.
Dinamikisht na duhet te ndertojme edhe pjesn e deklarates qe permban :fusha_1, :fusha_2, :fusha_3
. Veprojme ne te njejten menyre, vetem se stringa e bashkimit ndermjet elementeve te array-t do te jete , :
, ne menyre qe te perftojme rezultatin:
elementi_1, :elementi_2, :elementi_3 //etj...
Shohim qe perpara elementit te pare mungon shenja :
, per kete arsye vendosim edhe :
perpara shprehjes me ane te operatorit te bashkimit te stringave .
(concatenate).
<?php
// P.sh. kemi fushat e meposhtme:
$field_values = [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
"fusha_3" => "vlera_3"
];
$parametrat = ':' . implode(', :', array_keys($field_values));
echo $parametrat; // Rezultati: :fusha_1, :fusha_2, :fusha_3
Me njohurite qe perftuam nga shembujt qe dhame, implementojme metoden insert(...)
:
<?php
class Database {
private $connection;
function __construct() {
$host = "127.0.0.1"; //ose thjesht: localhost
$user = "root";
$password = ""; //Supozojme qe nuk kemi password per userin root
$db_name = "fakulteti";
try {
$this->connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
exit;
}
}
public function insert(string $table, array $field_values) {
$fushat = implode(',', array_keys($field_values));
$parametrat = ':' . implode(', :', array_keys($field_values));
$stmt = $this->connection->prepare("INSERT INTO $table ($fushat) VALUES ($parametrat);");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati) {
$id = $this->connection->lastInsertId();
return $id;
} else {
$error = $stmt->errorInfo();
return $error;
}
}
} // Fundi i klases Database
Nga sa shpjeguam mesiper, brenda funksionit insert(...)
ndertuam stringen $fushat
qe mban fushat ne formen fusha_1, fusha_2, fusha_3
, ndertuam stringen $parametrat
qe mban parametrat ne formen :fusha_1, :fusha_2, :fusha_3
. Ne metoden prepare(...)
kaluam deklaraten e parametrizuar INSERT INTO $table ($fushat) VALUES ($parametrat);
e cilar normalisht do te zevendesoje variablin $table
me emrin e tabeles te kaluar si argument ne funksion, dhe do te zevendesoje variablat $fushat
dhe $parametrat
me stringat perkatese qe paraqitem.
Pas krijimit te deklarates se parametrizuar, duhet te dergojme vlerat e parametrave me ane te metodes $stmt->bindValue(...)
. Per kete arsyeje ne perseritje ciklike kalojme pas cdo elementi te array-t $field_values
, te kaluar si argument. Gjate kalimit neper cdo element key => value
, therrasim $stmt->bindValue(":$key", $value);
per te derguar vlerat e parametrave ne formen $stmt->bindValue(":fusha_1", "vlera_1");
e keshtu me radhe. Ekzekutojme deklaraten duke therritur $rezultati = $stmt->execute();
dhe rezultati qe kthehet eshte TRUE
nese rekordi eshte shtuar me sukses, dhe FALSE
ne te kundert.
Ne shtimi i rekordit eshte i suksesshem kthejme id-ne e rekordit te shtuar, duke perdorur $this->connection->lastInsertId();
, perndryshe nese deshton shtimi i rekordit kthejme nje informacion rreth gabimit qe ndodhi $stmt->errorInfo();
.
Funksioni insert(...)
eshte gati per t'u perdorur. Le ta testojme:
<?php
$table = "departamentet";
$field_values = [
"emri" => "Departamenti i Elektronikes dhe Telekomunikacionit",
"pershkrimi" => "Pershkrimi i D.E.T."
];
$db = new Database();
$db->insert($table, $field_values);
Pas ekzekutimit te kodit te mesiperm, nese bejme nje SELECT
ne databaze do te shohim qe rekordi i ri gjendet ne tabele:
Komanda:
SELECT * FROM departamentet;
id | emri | pershkrimi |
---|---|---|
1 | Departamenti i Inxhinierise Informatike | Pershkrimi per departamentin e inxhinierise informatike. |
2 | Departamenti i Elektronikes dhe Telekomunikacionit | Pershkrimi i D.E.T. |
Modifikimi i nje rekordi ne nje tabele
Supozojme qe duam te modifikojme vleren e fushes pershkrimi
ne rekordin qe sapo shtuam. Ne kete rast, deklarata SQL qe do te nisim ka formen e meposhtme:
UPDATE departamentet SET pershkrimi = :pershkrimi WHERE id = 1;
Kodi PHP qe sherben per modifikimin e nje rekordi eshte si vijon:
<?php
// Supozojme qe lidhja $connection ishte e suksesshme
$stmt = $connection->prepare("UPDATE departamentet SET pershkrimi = :pershkrimi WHERE id = 1;");
// Vlera qe duam te modifikojme tek rekordi ne fjale:
$pershkrimi = "Pershkrimi i modifikuar.";
//Behet lidhja e parametrave me vlerat reale:
$stmt->bindValue(':pershkrimi', $pershkrimi);
// Faza e ekzekutimit:
$rezultati = $stmt->execute();
Pra, ashtu sic shtuam rekordin, ne te njejten menyre behet modifikimi. E vetmja gje qe ndryshon eshte deklarata SQL.
Pas ekzekutimit te kodit te mesiperm, nese bejme nje SELECT
ne databaze do te shohim qe rekordi i ri eshte modifikuar:
Komanda:
SELECT * FROM departamentet;
id | emri | pershkrimi |
---|---|---|
1 | Departamenti i Inxhinierise Informatike | Pershkrimi i modifikuar. |
Pasi trajtuam menyren sesi modifikohet nje rekord duke shfrytezuar klasen PDO
, le te ndertojme nje metode te klases Database
te quajtur update(...)
e cila do te jete dinamike, ne menyre te tille qe te funksionoje per cdo lloj tabele, dhe te mund te modifikoje fusha te ndryshme ne rekorde te ndryshme.
<?php
function update(string $table, array $field_values, string $where) {
}
Funksioni update(...)
do te pranoje tre argumente:
- Argumenti i pare do te jete nje string qe mban emrin e tabeles ne te cilen do te bejme modifikimin e rekordit
- Argumenti i dyte do te jete nje array associative
key => value
i cili do te mbaje sikeys
emrat e fushave te tabeles qe do te modifikohen, dhe sivalues
do te mbaje vlerat perkatese qe do te kene keto fusha - Argumenti i trete do te jete nje string qe mban kushtin
WHERE
, pa e perfshire vete terminWHERE
p.sh. mjaftonid = 1
dhe joWHERE id = 1
Dy argumentet e para do te kene te njejten forme si tek funksioni insert(...)
. Deklarata SQL e parametrizuar duhet te ndertohet ne formen e meposhtme:
UPDATE tabela_1 SET fusha_1 = :fusha_1, fusha_2 = :fusha_2, fusha_3 = :fusha_3 WHERE ...;
Kushti WHERE
vendoset sipas rastit p.sh. WHERE id = 10
ose WHERE fusha_x = 'Pershendetje'
etj.
Ndertojme ne menyre dinamike formatin: fusha_1 = :fusha_1, fusha_2 = :fusha_2, fusha_3 = :fusha_3
<?php
// P.sh. kemi fushat e meposhtme:
$field_values = [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
"fusha_3" => "vlera_3"
];
$fushe_vlerat = null;
foreach ($field_values as $key => $value) {
$fushe_vlerat .= "$key = :$key,";
}
$fushe_vlerat = rtrim($fushe_vlerat, ',');
echo $fushe_vlerat = null;; // Rezultati: fusha_1 = :fusha_1, fusha_2 = :fusha_2, fusha_3 = :fusha_3
Perdorim operatorin e bashkimit .
per te bashkuar elementet e array-t ne formen "$key = :$key,"
. Ne fund te te gjithe elementeve do te na krijohet edhe nje presje e tepert ,
. Me ane te funksionit rtrim
heqim presjen e fundit ,
.
Implementojme metoden update(...)
:
<?php
class Database {
private $connection;
function __construct() {
$host = "127.0.0.1"; //ose thjesht: localhost
$user = "root";
$password = ""; //Supozojme qe nuk kemi password per userin root
$db_name = "fakulteti";
try {
$this->connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
exit;
}
}
public function insert(string $table, array $field_values) {
$fushat = implode(',', array_keys($field_values));
$parametrat = ':' . implode(', :', array_keys($field_values));
$stmt = $this->connection->prepare("INSERT INTO $table ($fushat) VALUES ($parametrat);");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati) {
$id = $this->connection->lastInsertId();
return $id;
} else {
$error = $stmt->errorInfo();
return $error;
}
}
public function update(string $table, array $field_values, string $where) {
$fushe_vlerat = null;
foreach ($field_values as $key => $value) {
$fushe_vlerat .= "$key = :$key,";
}
$fushe_vlerat = rtrim($fushe_vlerat, ',');
$stmt = $this->connection->prepare("UPDATE $table SET $fushe_vlerat WHERE $where");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati)
return $rezultati;
else
return $stmt->errorInfo();
}
} // Fundi i klases Database
Deklarata SQL qe formohet eshte UPDATE $table SET $fushe_vlerat WHERE $where
ne te cilen $table
do te zevendesohet me emrin e tabeles, $fushe_vlerat
do te zevendesohen me stringen qe formohet fusha_1 = :fusha_1, fusha_2 = :fusha_2, fusha_3 = :fusha_3
, dhe $where
eshte kushti qe kemi kaluar si argument te trete. Duhet te kemi kujdes pasi kushti qe kalohet si argument nuk duhet te perfshije termin WHERE
.
Funksioni update(...)
eshte gati per t'u perdorur. Le ta testojme:
<?php
$table = "departamentet";
// Deklarojme vetem fushen qe duam te modifikojme:
$field_values = [
"pershkrimi" => "Pershkrimi i D.E.T. i modifikuar!"
];
$where = "id = 2";
$db = new Database();
$db->update($table, $field_values, $where);
Pas ekzekutimit te kodit te mesiperm, nese bejme nje SELECT
ne databaze do te shohim qe rekordi me id te barabarte me 2 eshte modifikuar:
Komanda:
SELECT * FROM departamentet;
id | emri | pershkrimi |
---|---|---|
1 | Departamenti i Inxhinierise Informatike | Pershkrimi per departamentin e inxhinierise informatike. |
2 | Departamenti i Elektronikes dhe Telekomunikacionit | Pershkrimi i D.E.T. i modifikuar! |
Selektimi (Marrja) e rekordeve nga nje tabele
Nese duam te marrim rekorde nga nje tabele ne databaze, deklarata SQL duhet te kete formen e meposhtme:
SELECT * FROM departamentet WHERE id = :id;
Dukeqenese do te ekzekutojme nje deklarate te pergatitur, ne kushtin WHERE
fushat i vendosim te parametrizuara, pra ne kete rast :id
.
Kodi PHP qe sherben per marrjen e rekordeve eshte si vijon:
<?php
// Supozojme qe lidhja $connection ishte e suksesshme
$stmt = $this->connection->prepare("SELECT * FROM departamentet WHERE id = :id;");
$stmt->bindValue(":id", 1);
$stmt->execute();
$rekordet = $stmt->fetchAll( PDO::FETCH_ASSOC );
Ne te njejten menyre si insert
dhe update
, po ashtu veprohet edhe me marrjen e rekordeve, me nje ndryshim te vetem qe pasi ekzekutohet deklarata SQL me ane te metodes execute()
, listen me rekorde te kthyer mund ta aksesojme nepermjet $stmt->fetchAll(...)
. Kjo metode pranon si argument nje konstante te klases PDO
, qe tregon menyren sesi do te kthehen rekordet. P.sh.
PDO::FETCH_ASSOC
- Kthen nje array qe permban si elemente, rekordet e kthyer ne forme array associative. P.sh. nese do te na kthehen 2 rekorde te tabeles, i kthen ne formen e meposhtme:
[
// rekordi i pare:
[0] => [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
....
]
//rekordi i dyte:
[1] => [
"fusha_1" => "vlera_1",
"fusha_2" => "vlera_2",
....
]
]
Pas ekzekutimit te kodit te mesiperm, $rekordet
do te jete nje array dydimensional me vlerat e meposhtme:
[
[0] => [
"id" => "1",
"emri" => "Departamenti i Inxhinierise Informatike",
"pershkrimi" => "Pershkrimi per departamentin e inxhinierise informatike."
]
]
Si mund ti aksesojme keto rekorde?
Variabli $rekordet
i kthyer pas ekzekutimit te deklarates SQL, mund te aksesohet dhe te perpunohet ne te njejten forme si cdo koleksion array. Shembull:
<?php
// Iterojme ne cdo rekord
foreach (rekordet as $key => $rekord) {
echo "Departamenti: " . $rekord['emri'] . '<br>';
echo "Pershkrimi: " . $rekord['pershkrimi'];
}
Rezultati i kodit te mesiperm:
Departamenti: Departamenti i Inxhinierise Informatike
Pershkrimi: Pershkrimi per departamentin e inxhinierise informatike.
Ne rast se nuk duam te perdorim ciklin foreach
, mund te veprojme si me poshte:
<?php
$departamenti = $rekordet[0]['emri'];
$pershkrimi = $rekordet[0]['pershkrimi'];
echo "Departamenti: " $departamenti . '<br>';
echo "Pershkrimi: " . $pershkrimi;
Dukeqenese array $rekordet
eshte dydimensional, vlerat e tij mund ti aksesojme edhe ne formen $rekordet[0]['emri']
, ku celesi 0
indekson rreshtin e pare. Menyra e nje indeksimi te tille kuptohet me qarte kur shohim paraqitjen e meposhtme te array-t $rekordet
:
// Array $rekordet:
[
[0] => [
"id" => "1",
"emri" => "Departamenti i Inxhinierise Informatike",
"pershkrimi" => "Pershkrimi per departamentin e inxhinierise informatike."
]
]
Ndertojme nje metode te klases Database
te quajtur select(...)
e cila do te jete dinamike.
<?php
function select(string $sql, array $bindArray = array(), $fetchMode = PDO::FETCH_ASSOC) {
}
Funksioni select(...)
do te pranoje tre argumente:
- Argumenti i pare do te jete nje string qe mban deklaraten SQL te parametrizuar (te tipit :fusha, ose jo.
- Argumenti i dyte do te jete nje array associative key => value i cili do te mbaje si keys parametrat te vendosur ne SQL te tipit :fusha, dhe si values do te mbaje vlerat perkatese qe do te kene keto parametra. Si vlere default ka nje array bosh, per rastin kur nuk kemi parametra ne SQL.
- Argumenti i trete do te jete nje konstante e klases
PDO
, e cila tregon se ne cfare menyre do te merren te dhenat. Ka nje vleren defaultPDO::FETCH_ASSOC
, pra nuk jemi te detyruar ta percaktojme.
Implementojme metoden select(...)
:
<?php
class Database {
private $connection;
function __construct() {
$host = "127.0.0.1"; //ose thjesht: localhost
$user = "root";
$password = ""; //Supozojme qe nuk kemi password per userin root
$db_name = "fakulteti";
try {
$this->connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
exit;
}
}
public function insert(string $table, array $field_values) {
$fushat = implode(',', array_keys($field_values));
$parametrat = ':' . implode(', :', array_keys($field_values));
$stmt = $this->connection->prepare("INSERT INTO $table ($fushat) VALUES ($parametrat);");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati) {
$id = $this->connection->lastInsertId();
return $id;
} else {
$error = $stmt->errorInfo();
return $error;
}
}
public function update(string $table, array $field_values, string $where) {
$fushe_vlerat = null;
foreach ($field_values as $key => $value) {
$fushe_vlerat .= "$key = :$key,";
}
$fushe_vlerat = rtrim($fushe_vlerat, ',');
$stmt = $this->connection->prepare("UPDATE $table SET $fushe_vlerat WHERE $where");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati)
return $rezultati;
else
return $stmt->errorInfo();
}
public function select(string $sql, array $bindArray = array(), $fetchMode = PDO::FETCH_ASSOC) {
$stmt = $this->connection->prepare($sql);
foreach ($bindArray as $key => $value) {
$stmt->bindValue("$key", $value);
}
$stmt->execute();
return $stmt->fetchAll( $fetchMode );
}
} // Fundi i klases Database
Funksioni select(...)
eshte gati per t'u perdorur. Le ta testojme:
<?php
$sql = "SELECT * FROM departamentet WHERE id = :id;";
$rekordet = $db->select($sql, [ ":id" => 1 ]);
echo "Departamenti: " $rekordet[0]['emri'] . '<br>';
echo "Pershkrimi: " . $rekordet[0]['pershkrimi'];
Rezultati:
Departamenti: Departamenti i Inxhinierise Informatike
Pershkrimi: Pershkrimi per departamentin e inxhinierise informatike.
Fshirja e nje rekordi nga nje tabele
Nese duam te fshijme nje rekord nga nje tabele ne databaze, deklarata SQL duhet te kete formen e meposhtme:
DELETE FROM departamentet WHERE id = 2;
Kodi PHP qe sherben per fshirjen e nje rekordi eshte si vijon:
<?php
$this->connection->exec("DELETE FROM departamentet WHERE id = 2;");
Metoda exec
qe kemi perdorur me lart ekzekuton menjehere deklaraten SQL, dhe na kthen si pergjigje numrin e rekordeve te afektuar. Ka raste qe mund kushtin WHERE
e plotesojne disa rekorde. Ne kete rast kthehet numri total i rekordeve qe afektohen. Deklarates DELETE
mund ti shtojme termin LIMIT
per te percaktuar numrin maksimal qe lejohet te afektohet ne nje deklarate te vetme. P.sh:
<?php
$this->connection->exec("DELETE FROM departamentet WHERE id IN (1, 2) LIMIT 1;");
Pavaresisht se kushtin e mesiperm e plotesojne me shume se nje rekord, fshihet vetem rekordi i pare ne radhe sepse kemi percaktuar limitin 1
.
Implementojme nje metode delete(...)
ne klasen Database
:
<?php
function delete(string $table, string $where, int $limit = 1) {
}
Funksioni delete(...)
do te pranoje tre argumente:
- Argumenti i pare do te jete nje string qe mban emrin e tabeles nga e cila do te fshijme rekordet
- Argumenti i dyte do te jete nje string qe mban kushtin
WHERE
, pa e perfshire vete termin WHERE p.sh. mjaftonid = 1
dhe joWHERE id = 1
- Argumenti i trete do te jete nje numer qe mban numrin maksimal te rekordeve qe do te fshihen. Nuk lejohet te fshihen me shume sesa numri i percaktuar ne kete argument.
Implementojme metoden delete(...)
:
<?php
class Database {
private $connection;
function __construct() {
$host = "127.0.0.1"; //ose thjesht: localhost
$user = "root";
$password = ""; //Supozojme qe nuk kemi password per userin root
$db_name = "fakulteti";
try {
$this->connection = new PDO("mysql:host=$host;dbname=$db_name", $user, $password);
// Vendosim metoden sesi PDO-ja do te gjeneroje gabimet - ne forme Exception:
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex) {
echo "Lidhja deshtoi: " . $ex->getMessage();
exit;
}
}
public function insert(string $table, array $field_values) {
$fushat = implode(',', array_keys($field_values));
$parametrat = ':' . implode(', :', array_keys($field_values));
$stmt = $this->connection->prepare("INSERT INTO $table ($fushat) VALUES ($parametrat);");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati) {
$id = $this->connection->lastInsertId();
return $id;
} else {
$error = $stmt->errorInfo();
return $error;
}
}
public function update(string $table, array $field_values, string $where) {
$fushe_vlerat = null;
foreach ($field_values as $key => $value) {
$fushe_vlerat .= "$key = :$key,";
}
$fushe_vlerat = rtrim($fushe_vlerat, ',');
$stmt = $this->connection->prepare("UPDATE $table SET $fushe_vlerat WHERE $where");
foreach ($field_values as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$rezultati = $stmt->execute();
if ($rezultati)
return $rezultati;
else
return $stmt->errorInfo();
}
public function select(string $sql, array $bindArray = array(), $fetchMode = PDO::FETCH_ASSOC) {
$stmt = $this->connection->prepare($sql);
foreach ($bindArray as $key => $value) {
$stmt->bindValue("$key", $value);
}
$stmt->execute();
return $stmt->fetchAll( $fetchMode );
}
public function delete(string $table, string $where, int $limit = 1) {
return $this->connection->exec("DELETE FROM $table WHERE $where LIMIT $limit");
}
} // Fundi i klases Database
Funksioni delete(...)
eshte gati per t'u perdorur. Le ta testojme:
<?php
$db = new Database();
$db->delete("departamentet", "id = 2");
Pas ekzekutimit te kodit te mesiperm, nese bejme nje SELECT
ne databaze do te shohim qe rekordi me id te barabarte me 2 eshte fshire:
Komanda:
SELECT * FROM departamentet;
id | emri | pershkrimi |
---|---|---|
1 | Departamenti i Inxhinierise Informatike | Pershkrimi per departamentin e inxhinierise informatike. |
Pas implementimit te metodave te klases Database
, ne mund ta perdorim ate per cfare do lloj tabele, per te bere shtime, modifikime, fshirje ose marrje rekordesh. Kete klase do t'a perdorim ne projektin real qe do te implementojme ne kapitujt ne vijim.